import time
import uuid
from datetime import datetime

from flask import Flask, request, jsonify
from apscheduler.schedulers.background import BackgroundScheduler
import jenkins
from pytz import timezone
import pandas as pd
import os

app = Flask(__name__)

# Jenkins服务器配置
JENKINS_URL = "http://192.168.251.13:8080/"
JENKINS_USER = "vp-tester"
JENKINS_PASSWORD = "Aa123456"
JENKINS_JOB_NAME = "NVR_AUTO_TEST"

# 初始化Jenkins连接
server = jenkins.Jenkins(JENKINS_URL, username=JENKINS_USER, password=JENKINS_PASSWORD)

# 初始化调度器
scheduler = BackgroundScheduler(timezone=timezone('Asia/Shanghai'))
scheduler.start()

# 用于存储自动调度任务的ID
scheduled_jobs = {}


def parse_trigger_time(trigger_time):
    # 将中文的星期转换为数字格式
    days_mapping = {
        '星期1': '0', '星期2': '1', '星期3': '2', '星期4': '3',
        '星期5': '4', '星期6': '5', '星期7': '6'
    }
    days = [days_mapping[day] for day in trigger_time.split(',') if days_mapping[day]]
    return days


def stop_device_builds(device_name):
    """
    停止指定设备的所有正在运行的Jenkins构建
    """
    if device_name not in scheduled_jobs:
        return

    # 获取所有正在运行的构建
    running_builds = []
    try:
        # 获取所有构建信息
        builds = server.get_job_info(JENKINS_JOB_NAME)['builds']
        for build in builds:
            build_number = build['number']
            build_info = server.get_build_info(JENKINS_JOB_NAME, build_number)

            # 检查构建是否正在运行且属于指定设备
            if build_info['building']:
                params = {p['name']: p['value'] for p in build_info['actions'][0]['parameters']
                          if 'parameters' in build_info['actions'][0]}
                if params.get('DEVICE_NAME') == device_name:
                    running_builds.append(build_number)
    except jenkins.JenkinsException as e:
        print(f"Error getting build info: {str(e)}")
        return False

    # 停止所有运行中的构建
    success = True
    for build_number in running_builds:
        try:
            server.stop_build(JENKINS_JOB_NAME, build_number)
            print(f"Stopped build {build_number} for device {device_name}")
            time.sleep(1)  # 添加短暂延迟，确保Jenkins有时间处理请求
        except jenkins.JenkinsException as e:
            print(f"Failed to stop build {build_number}: {str(e)}")
            success = False

    # 清理构建记录
    if device_name in scheduled_jobs:
        scheduled_jobs[device_name]['build_numbers'] = []

    return success


def trigger_jenkins_job(job_params, device_name=None):
    """
    触发Jenkins任务并记录构建信息
    """
    print(f"Executing job for device {device_name} with parameters: {job_params}")
    try:
        # 先停止该设备的所有正在运行的构建
        if device_name:
            stop_device_builds(device_name)
            time.sleep(2)  # 给Jenkins一些时间来处理停止请求

        # 触发新的构建
        build_number = server.build_job(JENKINS_JOB_NAME, job_params)
        print(f"Job triggered successfully for {device_name}, build number: {build_number}")

        # 记录构建信息
        if device_name and device_name in scheduled_jobs:
            scheduled_jobs[device_name]["build_numbers"].append(build_number)

        return {"status": "success", "build_number": build_number}
    except jenkins.JenkinsException as e:
        print(f"Failed to trigger job: {str(e)}")
        return {"status": "error", "error": str(e)}


@app.route('/schedule_job', methods=['POST'])
def schedule_job():
    data = request.get_json()
    trigger_time = data.get('trigger_time', '星期一')
    device_name = data.get('DEVICE_NAME')
    job_params = {k: v for k, v in data.items() if k != 'trigger_time'}

    # 如果已经有该设备的调度，先取消它们
    if device_name in scheduled_jobs:
        # 停止所有运行中的构建
        stop_device_builds(device_name)
        # 取消现有的调度
        for job_id in scheduled_jobs[device_name]["job_ids"]:
            scheduler.remove_job(job_id)

    # 解析调度时间并创建新的调度
    days = parse_trigger_time(trigger_time)
    job_ids = []
    for day in days:
        job_id = str(uuid.uuid4())
        scheduler.add_job(
            func=trigger_jenkins_job,
            trigger="cron",
            day_of_week=day,
            hour=6,
            minute=0,
            args=[job_params, device_name],
            id=job_id
        )
        job_ids.append(job_id)

    # 更新调度记录
    scheduled_jobs[device_name] = {
        "job_ids": job_ids,
        "build_numbers": []
    }

    # 如果当前日期匹配，立即执行
    current_day = str(datetime.now(timezone('Asia/Shanghai')).weekday())
    if current_day in days:
        print(f"Today matches trigger days. Executing job immediately for {device_name}")
        trigger_jenkins_job(job_params, device_name=device_name)

    return jsonify({
        "status": "success",
        "message": "Scheduled job added successfully",
        "job_ids": job_ids
    }), 200


@app.route('/manual_trigger', methods=['POST'])
def manual_trigger():
    data = request.get_json()
    device_name = data.get('DEVICE_NAME')
    job_params = {k: v for k, v in data.items() if k != 'trigger_time'}

    # 手动触发前也需要停止该设备的所有运行中的构建
    if device_name:
        stop_device_builds(device_name)
        time.sleep(2)  # 给Jenkins一些时间来处理停止请求

    result = trigger_jenkins_job(job_params, device_name=device_name)
    return jsonify(result)


@app.route('/cancel_schedule', methods=['POST'])
def cancel_schedule():
    data = request.get_json()
    device_name = data.get('DEVICE_NAME')

    if device_name in scheduled_jobs:
        # 停止所有运行中的构建
        stop_device_builds(device_name)

        # 取消调度任务
        for job_id in scheduled_jobs[device_name]["job_ids"]:
            try:
                scheduler.remove_job(job_id)
            except Exception as e:
                print(f"Failed to remove scheduled job {job_id}: {str(e)}")

        # 删除记录
        del scheduled_jobs[device_name]

        return jsonify({
            "status": "success",
            "message": "All jobs and builds canceled successfully",
            "device_name": device_name
        }), 200
    else:
        return jsonify({
            "status": "error",
            "message": "Device name not found",
            "device_name": device_name
        }), 404


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)